//
// Created by root on 4/29/17.
//

#ifndef FUNNY_RUNNER_SCHEME_H
#define FUNNY_RUNNER_SCHEME_H

#include "../base/cmocka_test.h"
#include "../../src/ds/string.h"
#include "../../src/scheme/basic/ds.h"
#include "../../src/scheme/basic/operator.h"

#define assert_cell_equal(_cell1,_cell2) assert_true(equal(global_scheme, _cell1, _cell2))
// #define assert_cell_equal1(_cell1,_cell2) assert_memory_equal(_cell1, _cell2, sizeof(Cell))

#define ASSERT_OP_IN_STACK(_op) assert_ptr_equal(pick_callstack_item(global_scheme, ITEM_OPERATOR), cell_op_##_op)

#define ASSERT_OP_CURRENT(_op) assert_ptr_equal(pick_current_item(global_scheme, ITEM_OPERATOR), cell_op_##_op)
#define ASSERT_CODE_CURRENT(_code) assert_memory_equal(pick_current_item(global_scheme, ITEM_CODE), _code, sizeof(Cell))

#define ASSERT_EMPTY_OP_IN_STACK assert_ptr_equal(pick_callstack_item(global_scheme, ITEM_OPERATOR), &g_nil)

#define EVAL_CODE_AND_RETURN(_code,_result) assert_cell_equal(global_scheme->code, _code); \
    global_scheme->returnValue = _result; \
    pop_callstack(global_scheme)


#define LIST_1(_a)                cons(global_scheme, _a, &g_nil)
#define LIST_2(_a,_b)             cons(global_scheme, _a, LIST_1(_b))
#define LIST_3(_a,_b,_c)          cons(global_scheme, _a, LIST_2(_b,_c))
#define LIST_4(_a,_b,_c,_d)       cons(global_scheme, _a, LIST_3(_b,_c,_d))
#define LIST_5(_a,_b,_c,_d,_e)    cons(global_scheme, _a, LIST_4(_b,_c,_d,_e))
#define LIST_6(_a,_b,_c,_d,_e,_f) cons(global_scheme, _a, LIST_5(_b,_c,_d,_e,_f))

#define TEST_INVALID_TYPE_EXCEPTION(_r) assert_string_equal(_r->_type, EXCEPTION_TYPE); \
    assert_string_equal(car(_r)->_string, "INVALID_TYPE")

#define TEST_DIVISION_BY_ZERO(_r) assert_true(eqe(_r, E_DIVISION_BY_ZERO))

Scheme *global_scheme;
int setup_scheme(void **state);
int teardown_scheme(void **state);
String interpret(String statement);

#endif //FUNNY_RUNNER_SCHEME_H
